package com.codeoss.framework.service.impl;

import java.sql.Timestamp;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.support.incrementer.OracleSequenceMaxValueIncrementer;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.codeoss.framework.context.UserContext;
import com.codeoss.framework.context.YunContext;
import com.codeoss.framework.db.util.OracleDataConvertUtil;
import com.codeoss.framework.db.util.SqlServerDataConvertUtil;
import com.codeoss.framework.model.BaseModel;
import com.codeoss.framework.service.IBaseService;

public class BaseService<M extends BaseMapper<T>, T> extends ServiceImpl<M,T> implements IBaseService<T>{
	@Value("${framework.db-type}")
	private String dbType;
	@Autowired
	private DataSource dataSource;
	@Transactional
	public void insert(T t) {
		setDefaultValue((BaseModel)t);
		boolean retValue=save(t);
		if(!retValue) {
			throw new RuntimeException("插入出现错误");
		}
	}
	
	@Transactional
	public boolean update(T t, Wrapper<T> updateWrapper) {
		YunContext yunContext=YunContext.getCurrentContext();
		yunContext.setAttribute("__modelupdate__", true);
		
		BaseModel baseModel=(BaseModel)t;
		baseModel.setUpdateDate(new Timestamp(System.currentTimeMillis()));
		
		UserContext userContext=UserContext.getCurrentUserContext();
		if(userContext!=null) {
			baseModel.setUpdateBy(userContext.getResUserId());	
		}
		boolean retValue=super.update(t, updateWrapper);
		if(!retValue) {
			throw new RuntimeException("不允许更新");
		}
		update(t);
		return retValue;
	}
	
	@Transactional
	public void update(T t) {
		YunContext yunContext=YunContext.getCurrentContext();
		Boolean hasUpdate=(Boolean)yunContext.getAttribute("__modelupdate__");
		if(hasUpdate!=null && hasUpdate.booleanValue()) {
			return;
		}
		BaseModel baseModel=(BaseModel)t;
		baseModel.setUpdateDate(new Timestamp(System.currentTimeMillis()));
		
		UserContext userContext=UserContext.getCurrentUserContext();
		if(userContext!=null) {
			baseModel.setUpdateBy(userContext.getResUserId());	
		}
		boolean retValue=super.updateById(t);
		if(!retValue) {
			throw new RuntimeException("更新出现错误");
		}
	}
	
	@Transactional
	public void delete(T t, QueryWrapper<T> updateWrapper) {
		YunContext yunContext=YunContext.getCurrentContext();
		yunContext.setAttribute("__modeldelete__", true);
		boolean retValue=remove(updateWrapper);
		if(!retValue) {
			throw new RuntimeException("不允许删除");
		}
		delete(t);
	}
	
	@Transactional
	public void delete(T t) {
		YunContext yunContext=YunContext.getCurrentContext();
		Boolean hasDelete=(Boolean)yunContext.getAttribute("__modeldelete__");
		if(hasDelete!=null && hasDelete.booleanValue()) {
			return;
		}
		BaseModel baseModel=(BaseModel)t;
		boolean retValue=super.removeById(baseModel.getId());
		if(!retValue) {
			throw new RuntimeException("删除出现错误");
		}
	}
	
	@Override
	public List<T> select(Wrapper<T> w) {
		// TODO Auto-generated method stub
		List<Object> list=listObjs(w);
		return (List<T>)list;
	}
	
	protected void setDefaultValue(BaseModel baseModel) {
		UserContext userContext=UserContext.getCurrentUserContext();
		if(userContext!=null) {
			if(baseModel.getResOrgId()==null) {
				baseModel.setResOrgId(userContext.getResOrgId());
			}
			if(baseModel.getCreateBy()==null) {
				baseModel.setCreateBy(userContext.getResUserId());
			}
			if(baseModel.getUpdateBy()==null) {
				baseModel.setUpdateBy(userContext.getResUserId());
			}
		}
		
		if(baseModel.getActive()==null) {
			baseModel.setActive(true);
		}
		if(baseModel.getCreateDate()==null) {
			baseModel.setCreateDate(new Timestamp(System.currentTimeMillis()));
		}
		if(baseModel.getUpdateDate()==null) {
			baseModel.setUpdateDate(new Timestamp(System.currentTimeMillis()));
		}
		if(baseModel.getVersion()==null) {
			baseModel.setVersion(1L);
		}
		
		if(baseModel.getId()==null && dbType.equals("oracle")) {
			String tableName=getTableName();
			System.out.println(tableName);
			OracleSequenceMaxValueIncrementer incr = new OracleSequenceMaxValueIncrementer(dataSource,tableName.replace("_",""));
			baseModel.setId(incr.nextLongValue());
		}
	}
	
	private String getTableName() {
		String className=this.getClass().getSimpleName();
		int index=className.indexOf("Service");
		className=className.substring(0, index);
		StringBuilder sb=new StringBuilder();
		for (int i=0;i<className.length();i++) {
			char c=className.charAt(i);
			if(c>='A' && c<='Z') {
				c=(char)(c+32);
				if(i>0) {
					sb.append("_");
				}
			}
			sb.append(c);
		}
		return sb.toString();
	}
	
	public List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper){
		List<Map<String, Object>> dataList=super.listMaps(queryWrapper);
		if(dbType.equals("oracle")) {
			dataList=OracleDataConvertUtil.doConvert(dataList);
		}else if(dbType.equals("sqlserver")) {
			dataList=SqlServerDataConvertUtil.doConvert(dataList);
		}
		return dataList;
	}
}

